/**
 * 版权所有(C)，中国银联股份有限公司，2002-2013，所有权利保留。
 * 
 * 项目名：	simple-core
 * 文件名：	GenericIbatisDao.java
 * 模块说明：	
 * 修改历史：
 * 2013-10-27 - Administrator - 创建。
 */
package com.aeky.simple.dao;

import java.io.Serializable;
import java.text.MessageFormat;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;

import com.aeky.simple.util.ReflectionUtils;
import com.aeky.simple.vo.page.Pager;
import com.ibatis.sqlmap.client.SqlMapClient;

/**
 * @author Administrator
 * 
 */
public abstract class GenericIbatisDao<T, PK extends Serializable> extends SqlMapClientDaoSupport {

    /** 日志 */
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private SqlMapClient sqlMapClient;

    /** 实体Class对象 */
    private Class<T> entityClass;

    /** 实体类名称（如：User） */
    private String entityClassName;

    /** 获取所有对象 */
    protected String queryAll;

    /** 根据主键获取对象 */
    protected String queryByPK;

    /** 根据主键和版本号查询对象 */
    protected String queryByPKAndVersion;

    /** 根据查询条件获取对象 */
    protected String queryByMap;

    /** 根据主键更新对象 */
    protected String updateByPK;

    /** 根据主键和版本号更新对象 */
    protected String updateByPKAndVersion;

    /** 更新对象 */
    protected String updateByMap;

    /** 新增对象 */
    protected String add;

    protected String addList;

    /** 根据条件删除对象 */
    protected String delete;

    /** 分页查询总条数 */
    protected String count;

    /** 分页查询对象 */
    protected String queryByPage;

    public GenericIbatisDao() {
        this.entityClass = ReflectionUtils.getSuperClassGenericType(getClass());
        this.entityClassName = this.entityClass.getSimpleName();
        this.queryAll = MessageFormat.format("{0}.queryAll", entityClassName);
        this.queryByPK = MessageFormat.format("{0}.queryByPK", entityClassName);
        this.queryByMap = MessageFormat.format("{0}.queryByMap", entityClassName);
        this.queryByPKAndVersion = MessageFormat.format("{0}.queryByPKAndVersion", entityClassName);
        this.updateByPK = MessageFormat.format("{0}.updateByPK", entityClassName);
        this.updateByPKAndVersion = MessageFormat.format("{0}.updateByPKAndVersion",
                        entityClassName);
        this.updateByMap = MessageFormat.format("{0}.updateByMap", entityClassName);
        this.add = MessageFormat.format("{0}.add", entityClassName);
        this.addList = MessageFormat.format("{0}.addList", entityClassName);
        this.delete = MessageFormat.format("{0}.delete", entityClassName);
        this.count = MessageFormat.format("{0}.count", entityClassName);
        this.queryByPage = MessageFormat.format("{0}.queryByPage", entityClassName);
    }

    /**
     * 获取所有的对象
     * 
     * @return
     */
    @SuppressWarnings("unchecked")
    protected List<T> queryAll() {
        return (List<T>) getSqlMapClientTemplate().queryForList(this.queryAll);
    }

    /**
     * 根据主键获取对象
     * 
     * @param id
     * @return
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    protected T queryByPK(PK id) {
        return (T) getSqlMapClientTemplate().queryForObject(this.queryByPK, id);
    }

    /**
     * 根据主键和乐观锁获取对象
     * 
     * @param entity
     * @return influencdRow 影响的记录数
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    protected T queryByPKAndVersion(Map<String, Object> paramMap) {
        return (T) this.getSqlMapClientTemplate()
                        .queryForObject(this.queryByPKAndVersion, paramMap);
    }

    /**
     * 根据查询条件查询
     * 
     * @param paramMap
     * @return
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    protected List<T> queryByMap(Map<String, Object> paramMap) {
        return (List<T>) getSqlMapClientTemplate().queryForList(this.queryByMap, paramMap);
    }

    /**
     * 根据主键更新对象(用于更新字段较多的情况使用)
     * 
     * @param entity
     * @return influencdRow 影响的记录数
     * @throws Exception
     */
    protected int updateByPK(T entity) {
        return getSqlMapClientTemplate().update(this.updateByPK, entity);
    }

    /**
     * 根据主键和乐观锁更新对象(用于更新字段较多的情况使用)
     * 
     * @param entity
     * @return influencdRow 影响的记录数
     * @throws Exception
     */
    protected int updateByPKAndVersion(T entity) {
        return getSqlMapClientTemplate().update(this.updateByPKAndVersion, entity);
    }

    /**
     * 根据条件更新数据(用于根据条件更新部分字段的值, 支持version灵活使用)
     * 
     * @param statementId
     * @return influencdRow 影响的记录数
     * @throws Exception
     */
    protected int updateByMap(Map<String, Object> paramMap) {
        return getSqlMapClientTemplate().update(this.updateByMap, paramMap);
    }

    /**
     * 新增对象
     * 
     * @param entity
     * @return Object(生成的主键值)
     */
    protected Object add(T entity) {
        return this.getSqlMapClientTemplate().insert(this.add, entity);
    }

    /**
     * 新增对象
     * 
     * @param entity
     * @return Object(生成的主键值)
     */
    protected Object addList(List<T> list) {
        return this.getSqlMapClientTemplate().insert(this.addList, list);
    }

    /**
     * 根据条件删除对象
     * 
     * @param entity
     * @return influencdRow 影响的记录数
     * @throws Exception
     */
    protected int delete(Map<String, Object> paramMap) {
        return getSqlMapClientTemplate().delete(this.delete, paramMap);
    }

    @SuppressWarnings("unchecked")
    protected Pager<T> queryByPage(Pager<T> pager, Map<String, Object> paramMap) {
        paramMap.put("startIndex", pager.getStartIndex());
        paramMap.put("endIndex", pager.getEndIndex());
        int totalCount = (Integer) this.getSqlMapClientTemplate().queryForObject(count, paramMap);
        List<T> list = this.getSqlMapClientTemplate().queryForList(queryByPage, paramMap);
        pager.setRows(list);
        pager.setTotal(totalCount);
        return pager;
    }

    @PostConstruct
    public void initSqlMapClient() {
        super.setSqlMapClient(sqlMapClient);
    }
}
